﻿//  -------------------- iSharePoint -------------------- //
// 
//  Company:	IT Complex, LLC
//  Project:	Smart.Common
//  File name:	TemplateService.cs
//  Developer:	Solomatov Igor
//  Created:	15.04.2012
// 
//  -------------------- iSharePoint -------------------- //

using System.Collections.Generic;
using System.Linq;

namespace Smart.Common.Templates
{
	/// <summary>
	/// Template service
	/// </summary>
	public abstract class TemplateService : ITemplateService
	{
		/// <summary>
		/// Template context
		/// </summary>
		public TemplateCtx Ctx { get; set; }

		/// <summary>
		/// Current template Source (lazy)
		/// </summary>
		public TemplateSource Source { get; set; }

		/// <summary>
		/// Current template Converter (lazy)
		/// </summary>
		public TemplateConverter Converter { get; set; }

		/// <summary>
		/// Current template Formatter (lazy)
		/// </summary>
		public TemplateFormatter Formatter { get; set; }

		/// <summary>
		/// Creates template context
		/// </summary>
		public virtual void InitContext(string serviceName)
		{
			Ctx =
				new TemplateCtx(serviceName)
					{
						Service = this
					};
		}

		/// <summary>
		/// Init service (also fills lazy properties)
		/// </summary>
		public virtual void InitService()
		{
			if (Source == null)
				Source = CreateSource();

			if (Converter == null)
				Converter = CreateConverter();

			if (Formatter == null)
				Formatter = CreateFormatter();
		}

		/// <summary>
		/// Create template source
		/// </summary>
		public abstract TemplateSource CreateSource();

		/// <summary>
		/// Create template formatter
		/// </summary>
		public abstract TemplateConverter CreateConverter();

		/// <summary>
		/// Create template formatter
		/// </summary>
		public abstract TemplateFormatter CreateFormatter();

		/// <summary>
		/// Create new template filter
		/// </summary>
		public virtual TemplateFilter CreateFilter()
		{
			return Source.CreateFilter();
		}

		/// <summary>
		/// Return templates using filter
		/// </summary>
		public virtual IList<ITemplate> GetTemplates(TemplateFilter filter)
		{
			return Source.LoadTemplates(filter);
		}

		/// <summary>
		/// Return templates using filter
		/// </summary>
		public virtual IList<TTemplatesType> GetTemplates<TTemplatesType>(TemplateFilter filter)
			where TTemplatesType : class, ITemplate
		{
			return GetTemplates(filter).Cast<TTemplatesType>().ToList();
		}

		/// <summary>
		/// Format template
		/// </summary>
		public virtual bool Format(string templateId, string instanceId, IDictionary<string, object> values)
		{
			if (templateId.IsNullOrEmpty() || instanceId.IsNullOrEmpty())
				return false;

			// Init context
			Ctx.TemplateId = templateId;
			Ctx.InstanceId = instanceId;

			// Load and create entities
			var template = Source.LoadTemplate(templateId);
			var instance = Source.CreateInstance(instanceId, template);

			// Perform format and save
			return
				Format(template, instance, values)
				&&
				instance.Save();
		}

		/// <summary>
		/// Format template
		/// </summary>
		public virtual bool Format(ITemplate template, ITemplateInstance instance, IDictionary<string, object> values)
		{
			if (template == null || instance == null)
				return false;

			// Init context
			Ctx.Template = template;
			Ctx.Instance = instance;

			// Load values
			Converter.LoadTemplateValuesToCtx();
			Converter.LoadUserValuesToCtx(values);

			// Perform format
			return
				Formatter.Format();
		}

		/// <summary>
		/// Format template
		/// </summary>
		public virtual object FormatData(object templateData, IDictionary<string, object> values)
		{
			if (templateData == null)
				return null;

			// Load values
			Converter.LoadUserValuesToCtx(values);

			return
				Formatter.Format(templateData);
		}

		/// <summary>
		/// Format template
		/// </summary>
		public virtual object FormatData(string templateId, IDictionary<string, object> values)
		{
			if (templateId.IsNullOrEmpty())
				return null;

			// Load template data
			var template = Source.LoadTemplate(templateId);
			var templateData = Source.LoadTemplateData(template);

			// Load values
			Converter.LoadUserValuesToCtx(values);

			// Perform format
			return
				Formatter.Format(templateData);
		}
	}
}